package cn.tedu.csmallsso.config;


import cn.tedu.csmallsso.filter.JwtAuthorizationFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

//SpringBoot中的配置类，需要添加@Configuration
@Configuration
@Slf4j
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启全局的授权访问检查
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthorizationFilter jwtAuthorizationFilter;

    //准备BCryptPasswordEncoder实例
    @Bean
    public PasswordEncoder passwordEncoder(){
        log.info("创建密码编码器组件: BCryptPasswordEncoder");
        return new BCryptPasswordEncoder();
    }
    //提供AuthenticationManager对象
    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    //重写configure()，用于配置HTTP请求的安全性。
    //可以通过调用HTTP对象上的方法来定期HTTP请求的授权规则、登录配置、注销配置和其他安全配置
    //配置白名单
    @Override
    protected void configure(HttpSecurity http) throws Exception{
        //设置白名单--不需要登录就可以访问(没有权限返回403[后续讲])
        String[] urls={
                "/admins/login",
                "/doc.html",
                "/**/*.css",
                "/**/*.js",
                "/favicon.ico",
                "/v2/api-docs",
                "/swagger-resources"
        };
        http.csrf().disable(); //禁止跨域。如果不禁止，白名单路径的异步访问会出现403错误
        http.cors(); //允许通过客户端的复杂类型的请求
        http.authorizeRequests()//请求需要被授权才可以访问
                .antMatchers(urls)//匹配某些路径
                .permitAll()//允许直接访问(不需要经过认证和授权)
                .anyRequest() //除了以上配置过的任何请求
                .authenticated();//通过认证才可以访问，登录后才能访问

        //添加处理JWT的过滤器，执行的顺序必须在处理用户名和密码的过滤器(内置的UsernamePasswordAuthenticationFilter)之前
        http.addFilterBefore(jwtAuthorizationFilter, UsernamePasswordAuthenticationFilter.class);


        //在路径中，可以使用*作为通配符；一个*表示匹配一层路径，两个*可以匹配多层路径
//        http.authorizeRequests() //请求需要被授权才可以访问
//                .antMatchers("/**") //匹配某些路径
//                .permitAll(); //允许直接访问(不需要经过认证和授权)

    }
}
